package com.ddm.service.impl.vxImpl;

import cn.hutool.Hutool;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddm.constant.MessageConstant;
import com.ddm.constant.VXConstant;
import com.ddm.context.BaseContext;
import com.ddm.dto.vxDTO.QuestionAnalysis;
import com.ddm.dto.vxDTO.TestDTO;
import com.ddm.entity.vxEntity.BonusPoints;
import com.ddm.entity.vxEntity.*;
import com.ddm.exception.DataErrorException;
import com.ddm.mapper.*;
import com.ddm.service.vxService.BonusPointService;
import com.ddm.service.vxService.ExamService;
import com.ddm.service.vxService.TestService;
import com.ddm.service.vxService.WrongQuestionService;
import com.ddm.utils.BeanCopyUtil;
import com.ddm.vo.vxVo.ScoreVO;
import com.ddm.vo.vxVo.TestVO;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author horizon
 * @since 2025-01-17
 */
@Service
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService {

    @Autowired
    ExamMapper examMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    ExamQuestionMapper examQuestionMapper;
    @Autowired
    QuetsionsMapper quetsionsMapper;
    @Autowired
    TestMapper testMapper;
    @Autowired
    ScoreMapper scoreMapper;
    @Autowired
    WrongQuestionMapper wrongQuestionMapper;
    @Autowired
    WrongQuestionService wrongQuestionService;
    @Autowired
    TestService testService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    ExamService examService;
    @Autowired
    BonusPointService bonusPointService;
    /**
     * 获取用户某场考试详细答题情况
     * @param testDTO
     * @return
     */
    @Override
    public List<TestVO> getTestById(TestDTO testDTO) {
        Exam exam = examMapper.selectOne(new LambdaQueryChainWrapper<Exam>(examMapper).eq(Exam::getExamName, testDTO.getExamName()));
        User user = userMapper.selectById(testDTO.getUserId());
        ExamQuestion examQuestion = examQuestionMapper.selectOne(new LambdaQueryChainWrapper<ExamQuestion>(examQuestionMapper).eq(ExamQuestion::getExamId, exam.getId()));
        Question question = quetsionsMapper.selectById(examQuestion.getQuestionId());
        if (exam == null || user ==null || examQuestion ==null){
            throw  new DataErrorException(MessageConstant.ERROR_DATA);
        }
        List<Test> testList = testMapper.selectList(new LambdaQueryChainWrapper<Test>(testMapper).eq(Test::getUserId, user.getId()).eq(Test::getExamId, exam.getId()));
        List<TestVO> testVOList = BeanCopyUtil.BeanCopyList(testList, TestVO.class);
        for (TestVO vo : testVOList) {
            vo.setExamName(exam.getExamName());
            vo.setUserName(user.getUserName());
            vo.setQuestionContent(question.getQuestionContent());
        }
        return testVOList;
    }


    /**
     * 用户某一张试卷的具体答题情况
     * @param testDTOS
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ScoreVO submitExam(Long examId, List<TestDTO> testDTOS) {
        //判断考试是否限时
        Exam exam = examMapper.selectById(examId);
        if (exam == null){
            throw new DataErrorException(MessageConstant.ERROR_DATA);
        }
        if (exam.getBeginTime()!=null && exam.getEndTime() !=null){
            //检验是否考试超时
            LocalDateTime now = LocalDateTime.now();
            if (now.isBefore(exam.getBeginTime())){
                throw new DataErrorException("考试还未开始");
            } else if (now.isAfter(exam.getEndTime())) {
                throw new DataErrorException("考试已经结束");
            }
        }
        List<Test> tests = BeanCopyUtil.BeanCopyList(testDTOS, Test.class);
        int totalScore = 0;
        int correctQuestionNum = 0;
        int wrongQuestionNum = 0;
        int totalAnswerTime = 0;
        //防止重复提交
        LambdaQueryWrapper<Score> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Score::getExamId,examId).eq(Score::getUserId,BaseContext.getCurrentId());
        Score exitScore = scoreMapper.selectOne(wrapper);
        String cacheKey = String.format(VXConstant.QUESTION_ANSWER_KEY, examId);
        ArrayList<WrongQuestion> wrongQuestions = new ArrayList<>();
        ArrayList<Test> insertTest = new ArrayList<>();
        //校验答案
        for (Test test : tests) {
            // 确保userId字段被正确设置
            if (test.getUserId() == null) {
                test.setUserId(BaseContext.getCurrentId());
            }
            if (test.getExamId() != examId){
                throw new DataErrorException(MessageConstant.ERROR_DATA);
            }
            String answer = (String) stringRedisTemplate.opsForHash().get(cacheKey, test.getQuestionId().toString());
            if (answer == null){
                answer = quetsionsMapper.selectById(test.getQuestionId()).getAnswer();
                stringRedisTemplate.opsForHash().put(cacheKey,test.getQuestionId().toString(),answer);
                stringRedisTemplate.expire(cacheKey,VXConstant.CACHE_TTL, TimeUnit.HOURS);
            }
            totalAnswerTime += test.getAnswerTime();
            boolean isCorrect = normalizeAnswer(test.getUserAnswer()).equals(normalizeAnswer(answer));
            test.setIsCorrect(isCorrect);
            if (isCorrect){
                test.setUserScore(test.getQuestionScore());
                totalScore +=test.getQuestionScore();
                correctQuestionNum+=1;
            }else {
                test.setUserScore(0);
                wrongQuestionNum+=1;
                //录入错题表
                WrongQuestion wrongQuestion = WrongQuestion.builder().questionId(test.getQuestionId()).userId(BaseContext.getCurrentId()).build();
                LambdaQueryWrapper<WrongQuestion> query = new LambdaQueryWrapper<>();
                query.eq(WrongQuestion::getQuestionId,test.getQuestionId()).eq(WrongQuestion::getUserId,BaseContext.getCurrentId());
                if (wrongQuestionMapper.selectOne(query)==null){
                    wrongQuestions.add(wrongQuestion);
                }
            }
            LambdaQueryWrapper<Test> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Test::getExamId,examId).eq(Test::getQuestionId,test.getQuestionId()).eq(Test::getUserId,BaseContext.getCurrentId());
            Test exitTest = testMapper.selectOne(queryWrapper);
            if (exitScore != null && exitTest !=null){
                testMapper.updateById(exitTest);
            }else {
                insertTest.add(test);
            }
        }
        if (exitScore!=null){
            exitScore.setTotalScores(totalScore);
            scoreMapper.updateById(exitScore);
        }else {
            Score score = Score.builder().examId(examId).totalScores(totalScore).userId(BaseContext.getCurrentId()).build();
            scoreMapper.insert(score);
        }
        testService.saveBatch(insertTest);
        wrongQuestionService.saveBatch(wrongQuestions);
        
        // 处理积分：总分多少就积多少积分
        Long currentUserId = BaseContext.getCurrentId();
        if (currentUserId != null && totalScore > 0) {
            // 查询用户现有积分
            LambdaQueryWrapper<BonusPoints> bonusQuery = new LambdaQueryWrapper<>();
            bonusQuery.eq(BonusPoints::getUserId, currentUserId);
            BonusPoints existingBonusPoints = bonusPointService.getOne(bonusQuery);
            
            if (existingBonusPoints != null) {
                // 更新现有积分
                existingBonusPoints.setPoints(existingBonusPoints.getPoints() + totalScore);
                bonusPointService.updateById(existingBonusPoints);
            } else {
                // 创建新的积分记录
                BonusPoints newBonusPoints = new BonusPoints();
                newBonusPoints.setUserId(currentUserId);
                newBonusPoints.setPoints(totalScore);
                bonusPointService.save(newBonusPoints);
            }
        }
        
        ScoreVO scoreVO = new ScoreVO();

        if (currentUserId == null) {
            throw new DataErrorException("用户未登录或登录已过期");
        }
        User user = userMapper.selectById(currentUserId);
        if (user == null) {
            throw new DataErrorException("用户信息不存在");
        }
        scoreVO.setUserName(user.getUserName());
        scoreVO.setTotalScores(totalScore);
        scoreVO.setExamName((exam.getExamName()));
        scoreVO.setCorrectQuestionNum((correctQuestionNum));
        scoreVO.setWrongQuestionNum(wrongQuestionNum);
        scoreVO.setTotalAnswerTime(totalAnswerTime);
        
        // 设置积分信息
        scoreVO.setBonusPoints(totalScore);
        
        // 添加题目解析信息
        List<QuestionAnalysis> questionList = examService.analysisQuestion(examId);
        scoreVO.setQuestionList(questionList);
        
        return scoreVO;
    }

    private String normalizeAnswer(String answer) {
        if (answer == null || answer.trim().isEmpty()) {
            return "";
        }
        // 处理无逗号的答案（如 "ACD" → "A,C,D"）
        String normalized = answer.replaceAll("([A-Za-z])", "$1,")  // 字母后加逗号
                .replaceAll(",+,", ",")          // 去重逗号
                .replaceAll("^,|,$", "");        // 去除首尾逗号
        return Arrays.stream(normalized.split(","))
                .map(String::trim)
                .map(String::toUpperCase)
                .sorted()
                .collect(Collectors.joining(","));
    }

}








